package com.iflytek.elpmobile.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.Map;

import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;

public class FileDownloader {
	public interface OnDownloadProgressListener {
		void onDownloadStart(String path, int total);

		void onDownloadProgress(int cur);

		void onDownloadData(byte buf[], int start, int length);
	}

	public interface OnDownloadCompleteListener {
		void onDownloadComplete(String url, int sizeOfByte);

		void onDownloadFailed();
	}

	// public void setOnDownloadProgressListener(OnDownloadProgressListener l){
	// mOnDownloadProgressListener = l;
	// }
	static private String getTempPath(Context context) {
		String filePath = Environment.getExternalStorageDirectory().getPath()
				+ File.separator + "iflytek" + File.separator
				+ context.getPackageName() + File.separator
				+ "DownloadFileCache";
		// Log.v("FileDownloader", filePath);
		File file = new File(filePath);
		if (!file.exists()) {
			file.mkdir();
		}
		return filePath;
	}

	// String mFileName;
	public String checkCacheFile(Context context, String url) {
		String fileName = getFileName(context, url);
		String filePath = getTempPath(context) + File.separator + fileName;
		File file = new File(filePath);
		if (file.exists()) {
			return filePath;
		}

		return null;
	}

	public String downloadFile(Context context, String url,
			OnDownloadProgressListener l) {
		String fileName = getFileName(context, url);
		// String filePath = getTempPath(context) + File.separator + fileName;
		String filePath = "sdcard/iflytek/englishweekly/" + fileName;
		File file = new File(filePath);

		if (file.exists()) {
			return filePath;
		}

		new Thread(new DownloadRunnable(filePath, url, l)).start();
		return null;
	}

	public String downloadFile(Context context, Uri uri,
			OnDownloadProgressListener l) {
		return downloadFile(context, uri.toString(), l);
	}

	/**
	 * 下载文件到指定位置
	 * 
	 * @author jgzheng
	 * @param uri
	 * @param path
	 */
	public String downloadFile(String url, String path,
			OnDownloadCompleteListener completeListener) {
		File file = new File(path);

		if (file != null && !file.exists()) {
			new Thread(new DownloadRunnable(path, url, completeListener))
					.start();
			return null;
		} else
			return path;

	}

	/**
	 * 下载文件到指定位置
	 * 
	 * @author jgzheng
	 * @param uri
	 * @param path
	 */
	public String downloadFile(String url, String path,
			OnDownloadProgressListener progressListener,
			OnDownloadCompleteListener completeListener) {
		File file = new File(path);

		if (file != null && !file.exists()) {
			new Thread(new DownloadRunnable(path, url, progressListener,
					completeListener)).start();
			return null;
		} else
			return path;

	}

	private String getFileName(Context context, String url) {
		SharedPreferences cacheFile = context.getSharedPreferences(
				"FileDownloader", Context.MODE_PRIVATE);
		String name = cacheFile.getString(url, null);
		if (null == name) {
			int index = cacheFile.getInt("CacheFileIndex", 0);
			index += 1;
			SharedPreferences.Editor editor = cacheFile.edit();
			editor.putInt("CacheFileIndex", index);
			editor.commit();

			int pointI = url.lastIndexOf('.');
			String fileSuffix;
			if (pointI > 0)
				fileSuffix = url.substring(pointI);
			else
				fileSuffix = ".mp3";

			name = "FileDownloader" + index + fileSuffix;
			editor.putString(url, name);
			editor.commit();

			String filePath = getTempPath(context) + File.separator + name;
			File file = new File(filePath);
			if (file.exists()) {
				file.delete();
			}
		}
		return name;
	}

	public static void RecursionDeleteFile(File file) {
		if (file.isFile()) {
			file.delete();
			return;
		}
		if (file.isDirectory()) {
			File[] childFile = file.listFiles();
			if (childFile == null || childFile.length == 0) {
				file.delete();
				return;
			}
			for (File f : childFile) {
				RecursionDeleteFile(f);
			}
			file.delete();
		}
	}

	static public void clearCache(Context context) {
		SharedPreferences cacheFile = context.getSharedPreferences(
				"FileDownloader", Context.MODE_PRIVATE);
		cacheFile.edit().clear().commit();
		RecursionDeleteFile(new File(getTempPath(context)));
	}

	private class DownloadRunnable implements Runnable {
		private OnDownloadProgressListener mOnDownloadProgressListener;
		private OnDownloadCompleteListener mOnDownloadCompleteListener;
		int mFileSize;
		int mDownloadCur;
		String mFilePath;
		String mFileUrl;
		URL mURL;

		public DownloadRunnable(String filepath, String url,
				OnDownloadProgressListener l) {
			mFileUrl = url;
			mOnDownloadProgressListener = l;
			mFilePath = filepath;
		}

		public DownloadRunnable(String filepath, String url,
				OnDownloadCompleteListener l) {
			mFileUrl = url;
			mOnDownloadCompleteListener = l;
			mFilePath = filepath;
		}

		public DownloadRunnable(String filepath, String url,
				OnDownloadProgressListener pl, OnDownloadCompleteListener l) {
			mFileUrl = url;
			mOnDownloadProgressListener = pl;
			mOnDownloadCompleteListener = l;
			mFilePath = filepath;
		}

		//fix BUG2014052600396 下载时写入tmp文件，防止还未完全下载结束就就读取文件
		@Override
		public void run() {
			try {
				URL url;
				if (null == mURL)
					url = new URL(mFileUrl);
				else
					url = mURL;

				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.addRequestProperty("Accept-Encoding", "identity");
				conn.connect();
				InputStream is = conn.getInputStream();

				mFileSize = conn.getContentLength();
				// Log.v("FileDownloader", "ContentLength = " + mFileSize);
				if (null != mOnDownloadProgressListener)
					mOnDownloadProgressListener.onDownloadStart(mFilePath,
							mFileSize);
				File file = new File(mFilePath + ".tmp");
				if(file.exists()){
					file.delete();
				}
				FileOutputStream fos = new FileOutputStream(file);

				mDownloadCur = 0;
				byte buf[] = new byte[1024];

				do {
					int numread = is.read(buf);
					if (numread <= 0) {
						// 下载出错
						if (mDownloadCur != mFileSize) {
							file.delete();
						}
						// 下载完成
						break;
					}
					mDownloadCur += numread;
					if (null != mOnDownloadProgressListener) {
						mOnDownloadProgressListener
								.onDownloadProgress(mDownloadCur * 100
										/ mFileSize);
						mOnDownloadProgressListener.onDownloadData(buf, 0,
								numread);
					}

					fos.write(buf, 0, numread);
				} while (true);

				fos.close();
				is.close();

				File down = new File(mFilePath+ ".tmp");
				if (down != null && down.exists()) {
					file.renameTo(new File(mFilePath));
					
					if (mOnDownloadCompleteListener != null) {
						mOnDownloadCompleteListener.onDownloadComplete(
								mFileUrl, mFileSize);
					}
				} else {
					if (mOnDownloadCompleteListener != null) {
						mOnDownloadCompleteListener.onDownloadFailed();
					}
				}

			} catch (Exception e) {
				File file = new File(mFilePath + ".tmp");
				if(file.exists()){
					file.delete();
				}
				if (mOnDownloadCompleteListener != null) {
					mOnDownloadCompleteListener.onDownloadFailed();
				}
				e.printStackTrace();
			}
		}
	};

	private static FileDownloader mFileDownloader;

	static public FileDownloader sharedInstance() {
		if (null == mFileDownloader) {
			mFileDownloader = new FileDownloader();
		}
		return mFileDownloader;
	}

	private FileDownloader() {

	}

	// 计算文件夹大小
	static public long getFileSize(File f) throws Exception {
		long size = 0;
		File flist[] = f.listFiles();
		for (int i = 0; i < flist.length; i++) {
			if (flist[i].isDirectory()) {
				size = size + getFileSize(flist[i]);
			} else {
				size = size + flist[i].length();
			}
		}
		return size;
	}

	static public String FormetFileSize(long fileS) {// 转换文件大小
		DecimalFormat df = new DecimalFormat("0.00");
		String fileSizeString = "";
		if (fileS < 1024) {
			fileSizeString = df.format((double) fileS) + "B";
		} else if (fileS < 1048576) {
			fileSizeString = df.format((double) fileS / 1024) + "K";
		} else if (fileS < 1073741824) {
			fileSizeString = df.format((double) fileS / 1048576) + "M";
		} else {
			fileSizeString = df.format((double) fileS / 1073741824) + "G";
		}
		return fileSizeString;
	}

	static public String getCacheSize(Context context) {
		try {
			return FormetFileSize(getFileSize(new File(getTempPath(context))));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "0";
	}
}
